package com.kun.framework.data.persistence.rule;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.ArrayUtil;
import com.kun.framework.core.exception.Assert;
import com.kun.framework.data.persistence.enums.PersistenceFileTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;

/**
 * 多文件规则
 *
 * @author gzc
 * @since 2024/8/21
 **/
public class MultipleFileRuler implements FileCreateRule {
    private final static Logger log = LoggerFactory.getLogger(MultipleFileRuler.class);

    /**
     * 保留文件数量，超过则删除时间最久远的缓存数据文件
     */
    protected int retainFileCount = 10;

    public MultipleFileRuler() {
    }

    public MultipleFileRuler(int retainFileCount) {
        if (retainFileCount < 1) {
            Assert.throwBizException("最大保留文件数据不能小于1");
        }
        this.retainFileCount = retainFileCount;
    }


    @Override
    public String getOutputFileName() {
        return DateUtil.date().toString("yyyyMMddHHmmss");
    }

    @Override
    public String getInputFilePath(String baseStorageDirPath, PersistenceFileTypeEnum fileTypeEnum) {
        if (FileUtil.isFile(baseStorageDirPath)) {
            Assert.throwBizException("参数 -> {}，不能是文件！", baseStorageDirPath);
        }
        String inputFilePath = baseStorageDirPath + File.separator + getOutputFileName();
        // 读取最新的缓存数据文件
        if (FileUtil.exist(baseStorageDirPath)) {
            // 获取缓存数据文件目录下所有缓存数据文件
            File[] fileArr = FileUtil.ls(baseStorageDirPath);
            if (ArrayUtil.isNotEmpty(fileArr)) {
                // 根据日期排序，获取最新文件
                Optional<File> fileOptional = Arrays.stream(fileArr).max(Comparator.comparingLong(File::lastModified));
                if (fileOptional.isPresent()) {
                    inputFilePath = fileOptional.get().getAbsolutePath();
                }
            }
        } else {
            // 创建目录
            FileUtil.mkdir(baseStorageDirPath);
        }
        return inputFilePath;
    }

    @Override
    public String getOutputFilePath(String baseStorageDirPath, PersistenceFileTypeEnum fileTypeEnum) {
        // 检查保留的缓存文件数量，超出限制数量则删除
        checkRetainFileCount(baseStorageDirPath);
        // 拼接输出文件完整路径
        String outputFileName = getOutputFileName();
        String outputFilePath = baseStorageDirPath + File.separator + outputFileName + StrPool.DOT + fileTypeEnum;
        // 如果文件存在并且不允许覆盖原文件，则修改输出文件名称
        if (FileUtil.exist(outputFilePath) && !isOverride()) {
            outputFilePath = baseStorageDirPath + File.separator + outputFileName + "(1)" + StrPool.DOT + fileTypeEnum;
        }
        return outputFilePath;
    }

    @Override
    public boolean isOverride() {
        return false;
    }

    /**
     * 检查保留的缓存文件数量，超出限制数量则删除
     */
    public synchronized void checkRetainFileCount(String storageFileDir) {
        // 根据最后修改时间排序
        List<File> fileList = Arrays.stream(FileUtil.ls(storageFileDir)).sorted(Comparator.comparing(File::lastModified)).toList();
        if (CollUtil.isEmpty(fileList)) {
            return;
        }
        // 计算超出最大文件数限制的超出文件总数
        int difference = fileList.size() - retainFileCount;
        if (difference <= 0) {
            return;
        }
        for (int i = 0; i < difference; i++) {
            File file = fileList.get(i);
            if (!FileUtil.del(file)) {
                Assert.throwBizException("删除超量缓存文件失败, 文件目录-> {}" + file.getAbsolutePath());
            }
            log.info("删除超量的缓存文件 -> {}", file.getAbsolutePath());
        }
    }

}
